package it.polimi.jita.cp;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.apache.commons.math3.distribution.NormalDistribution;
import org.apache.commons.math3.distribution.RealDistribution;

public class Sketchbook {
	static double M_ON = 2160d;
	static double M_OFF = 864d;
	static double PRECISION = 0.001;

	public static void main(String[] args) {
		Map<Integer, Double> ons = new TreeMap<>();
		Map<Integer, Double> offs = new TreeMap<>();
		// ons.put(75, 4d);
		// ons.put(1, 16d);
		// ons.put(50, 2d);

		offs.put(1, 16d);

		double sum = 0;
		for (int i = 0; i < 4000; i++) {
			increment(ons, offs);
			double newSum = sum(ons);
			System.out.println(newSum);
			// if (Math.abs(newSum - sum) < PRECISION)
			// break;
			sum = newSum;
		}

		System.out.println("on: " + sum(ons));
		System.out.println("off: " + sum(offs));
	}

	private static Double sum(Map<Integer, Double> ons) {
		Double sum = 0d;
		for (Entry<Integer, Double> eOn : ons.entrySet()) {
			sum += eOn.getValue();
		}
		return sum;
	}

	private static void increment(Map<Integer, Double> ons,
			Map<Integer, Double> offs) {
		// RealDistribution pOff = new ExponentialDistribution(M_OFF);
		// RealDistribution pOn = new ExponentialDistribution(M_ON);
		RealDistribution pOff = new NormalDistribution(M_OFF, 200d);
		RealDistribution pOn = new NormalDistribution(M_ON, 80d);
		// RealDistribution pOff = new ChiSquaredDistribution(M_OFF);
		// RealDistribution pOn = new ChiSquaredDistribution(M_ON);

		Map<Integer, Double> onNew = new HashMap<>();
		onNew.put(1, 0d);

		Map<Integer, Double> offNew = new HashMap<>();
		offNew.put(1, 0d);

		for (Entry<Integer, Double> eOn : ons.entrySet()) {
			Double offZeroToAdd = offNew.get(1);
			offZeroToAdd += pOff.cumulativeProbability(eOn.getKey() + 1)
					* eOn.getValue();
			offNew.put(1, offZeroToAdd);

			Integer newId = eOn.getKey() + 1;
			onNew.put(newId, (1 - pOff.cumulativeProbability(eOn.getKey() + 1))
					* eOn.getValue());
		}

		for (Entry<Integer, Double> eOff : offs.entrySet()) {
			Double onZeroToAdd = onNew.get(1);
			onZeroToAdd += pOn.cumulativeProbability(eOff.getKey() + 1)
					* eOff.getValue();
			onNew.put(1, onZeroToAdd);

			Integer newId = eOff.getKey() + 1;
			offNew.put(
					newId,
					(1 - pOn.cumulativeProbability(eOff.getKey() + 1))
							* eOff.getValue());
		}

		ons.clear();
		ons.putAll(onNew);
		offs.clear();
		offs.putAll(offNew);

	}
}
